package com.jy.rhin.domain.notification.subscribe;

import com.jy.rhin.domain.exception.RhinInfraErrorType;
import com.jy.rhin.domain.notification.subscribe.entity.SubscribeDO;
import com.jy.rhin.infra.uitl.Asserts;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * @author WeiQ
 * @date 2022/6/28 10:05
 * 主题订阅管理域服务
 */
@Service
public class SubscribeDomainService {

    @Resource
    SubscribeDao subscribeDao;

    /**
     * 根据id查询主题订阅记录
     *
     * @param id
     * @return
     */
    public SubscribeDO queryById(Long id) {
        return subscribeDao.queryById(id);
    }

    /**
     * 订阅主题
     * 1、 判断是新增还是编辑
     * 1.1 如果是新增，判断订阅者是否已经订阅过该主题
     * 1.2 如果是编辑，判断当前订阅是否存在
     *
     * @param subscribeDO
     * @return
     */
    public Long subscribe(SubscribeDO subscribeDO) {
        Long id = subscribeDO.getId();
        if (Objects.isNull(id)) {
            //新增
            //根据 订阅者+订阅主题 查询到订阅记录，说明重复订阅
            SubscribeDO origin = subscribeDao.queryBySubscriberAndTopic(subscribeDO.getSubscriberCode(), subscribeDO.getTopicExp());
            Asserts.isNull(origin, RhinInfraErrorType.SUBSCRIBE_EXISTS);
        } else {
            //更新
            SubscribeDO origin = queryById(id);
            Asserts.nonNull(origin, RhinInfraErrorType.SUBSCRIBE_NOT_FOUNT);
            //验证数据是否能够更新
            origin.accessUpdate(subscribeDO.getSubscriberCode(), subscribeDO.getTopicExp());
            //更新时订阅者标识号、创建人和创建时间不更新
            subscribeDO.updateSubscribeDefault(origin.getSubscribeUid(), origin.getCreateBy(), origin.getCreateTime());
        }
        subscribeDao.save(subscribeDO);
        return subscribeDO.getId();
    }

    /**
     * 取消订阅
     *
     * @param id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean cancelSubscribe(Long id, String operator) {
        SubscribeDO subscribe = queryById(id);
        Asserts.nonNull(subscribe, RhinInfraErrorType.SUBSCRIBE_NOT_FOUNT);
        //根据状态判断是否能够取消
        Asserts.isTrue(subscribe.cancel(operator), RhinInfraErrorType.SUBSCRIBE_STATUS_NOT_CANCEL);
        return subscribeDao.update(subscribe);
    }
    
    @Transactional(rollbackFor = Exception.class)
    public Boolean pauseSubscribe(Long id, String operator) {
        SubscribeDO subscribe = queryById(id);
        Asserts.nonNull(subscribe, RhinInfraErrorType.SUBSCRIBE_NOT_FOUNT);
        Asserts.isTrue(subscribe.pause(operator), RhinInfraErrorType.SUBSCRIBE_STATUS_NOT_CANCEL);
        return subscribeDao.update(subscribe);
    }
    
    @Transactional(rollbackFor = Exception.class)
    public Boolean resumeSubscribe(Long id, String operator) {
        SubscribeDO subscribe = queryById(id);
        Asserts.nonNull(subscribe, RhinInfraErrorType.SUBSCRIBE_NOT_FOUNT);
        Asserts.isTrue(subscribe.resume(operator), RhinInfraErrorType.SUBSCRIBE_STATUS_NOT_CANCEL);
        return subscribeDao.update(subscribe);
    }
}
